package sudoku;

import java.util.Scanner;
import java.util.Timer;
 
public class Sudoku_main {	
	static Scanner scanner = new Scanner(System.in);
	public static void main(String[] args) {
             IO();

	}
	
	//check if the difficulties_input correct
	public static int chooseDifficulties() {
		boolean difficulties_input=false;
		int difficulties = 0;

		while(difficulties_input==false)
		{
			//input the difficulties
			System.out.print("Select the difficulties ([1]easy, [2]medium, [3]difficult): ");
			difficulties = scanner.nextInt();
			difficulties_input=checkDifficulties(difficulties,difficulties_input);
		}
		return difficulties;
	}
	
	//check if the difficulties_input correct
	public static boolean checkDifficulties(int difficulties,boolean difficulties_input) {
		
		if(difficulties <1 || difficulties >3)
			System.out.println("input must between 1-3");
		else
			difficulties_input=true;
		
		return difficulties_input;
		
	}
	
	//check if the qustion_input correct
	public static int chooseQuestion(){
		boolean qustion_input=false;
		int question_no = 0;

		while(qustion_input==false)
		{
			System.out.print("Choose the qustion (1, 2, 3): ");
			question_no = scanner.nextInt();
			qustion_input=checkQuestion(question_no,qustion_input);
		}
		return question_no;
	}
	
	//check if the Question_input correct
	public static boolean checkQuestion(int question_no,boolean qustion_input) {
		
		if(question_no <1 || question_no >3)
			System.out.println("input must between 1-3");
		else
			qustion_input=true;
		
		return qustion_input;
		
	}
	
	public static boolean invalidLength_Range(Manager m,String input)
	{
		 if(m.is_invalid_length(input) || m.is_invalid_range(input))
		 {
			 System.out.println("Wrong input format");
			 return true;
		 }
		 else
			 return false;
	}
	public static boolean invalidLength_Range_Position(Manager m,String input,int xPosition,int yPosition)
	{
		if(m.is_invalid_length(input) || ( m.is_invalid_value(input) && m.contain_nonzero_position(xPosition, yPosition) ))
		{
			return true;
		}
		else
			return false;
			
			
	}
 	public static void IO()
 	{
        //restart means to reset any data stored including step and timer and restart the whole game, user need to choose difficulties and question again
 		//reset means to initialize the current question but the step and timer are not reset and continue to counting, user re do the question.
 		//change question means to choose other question in the same difficulties but the step not reset and timer is reset. user don't need to choose difficulties again
 		//surrender means to give up and choose if want to restart the whole game, if choose not, exit. It shows the answer of the current question and maybe will counting whole score in future
 		//timer start timing after choose difficulties.
 		boolean restart = true;
 		while(restart)
 		{
 			char input_no;
 			int xPosition = 0;
 			int yPosition = 0;
 			String input;
 			int step=0;
 			int difficulties=1; //default difficulties, will be change later
 			int question_no=0;	//default question_no, will be change later
 			int change_question_left = 2;	//how many time allow user to change question
 			Timer t = new Timer();
 			int display = 1; //0 means dont show the error message , 1 means dispaly the error message
 			//ask user to choose difficulties
 			difficulties=chooseDifficulties();
 			
 			//check if user need to change question
 			boolean need_change_question = true;
 			while (need_change_question==true)
 			{
 				t = new Timer();//initialize again to make sure there is timer when no run restart 
				//after choosing difficulties, show 3 question first to user choose
				System.out.println("The question set contains 3 questions" );
				for(int i=0;i<3;i++)
				{
					System.out.println("Qustion " + (i+1)+":" );
					Manager m=new Manager(difficulties,i);
					m.print_board();
				}
			
				//ask user to choose question 
				question_no = chooseQuestion() - 1; //question_no start from 0 in Manager
				
				//print board
				Manager m=new Manager(difficulties,question_no);
				m.print_board();		
				
				
				System.out.println("\nGuideline: The top left point's x coordinate and y ooordinate are 0");
				
				if(restart == true)
				{
		 			//Set up the timer
		
				    int s=0; 
				    switch (difficulties)
				    {
				    	case 1 : s = 900; break;
				    	case 2 : s = 720; break;
				    	case 3 : s = 540; break;
				    }
				    MyTimer mt=new MyTimer(t,s);
				    
				    //Start count down and decide to let current thread sleep for 0.1 seconds
				    t.scheduleAtFixedRate(mt,0,1000); 
				    try
				 	{
				    	Thread.sleep(100);  
				  
				 	}catch (InterruptedException ie){}
				  
				}
				
				//check if the game is over, start from here no step will be reset
				Boolean gameover = false;
				Boolean reset_question = false;
				while(!gameover)	   
				{	
						restart=false;
						if (reset_question == true)
						{
							//print board
							System.out.println("Reset the question");
							m=new Manager(difficulties,question_no);
							m.print_board();
							reset_question=false;
						}
						
						//check and ask user to input
						input="initial";
						input_no='e';
						boolean input_format=false;
						while (input_format==false)
						{
						   System.out.print("Enter Number(Input X Y coodinates & Number with SPACE Eg. 1 2 3)");
						   System.out.println(" or Get Hint(Input:0 0 h) or Surrender (Input:0 0 s) or Restart (Input:0 0 r) or Reset (Input: 0 0 t) or Exit (Input:0 0 e) or Change question (Input: 0 0 c)");
						   System.out.print("Please input: ");
						   
						   //scan x
						   input=scanner.next();
						   //delegate manager to check
						   if(invalidLength_Range(m,input))
						   {
							  
							   input_format=false;
							   input=scanner.nextLine();
						   }
						   else
						   {
							   xPosition = input.charAt(0)-'0';
							   
							   //scan y
							   input=scanner.next();
							   //delegate manager to check
							   if(invalidLength_Range(m,input))
							   {
								   input_format=false;
								   input=scanner.nextLine();
							   }
							   else
							   {
								   yPosition = input.charAt(0)-'0';
								   
								   //scan z
								   input=scanner.next();
								   //delegate manager to check 
								   if(invalidLength_Range_Position(m,input,xPosition,yPosition))
								   {
									   System.out.println("Wrong input format");
									   input_format=false;
									   input=scanner.nextLine();
								   }
								   else
								   {
									   input_no = input.charAt(0);
									   input_format=true;
								   }
							   }
					   		}
					   }
					   if (input_no=='e')
					   {
						   System.out.println("Game exit");  
						   System.exit(0);
					    }

					   else if (input_no=='r')
					   {
						   restart=true;
						   gameover=true;
						   need_change_question=false;
						   System.out.println("Restart the game");
						   t.cancel(); //Cancel current timer
					
					   }
					   
					   else if (input_no=='s')
					   {
						   t.cancel(); //Cancel current timer
						   System.out.println("Answer:");
						   m.surrender();
						   System.out.println("Game Over!");
						   gameover = true;
						   need_change_question=false;
						   System.out.print("Restart the game? Input[0]Restart [1]Exit: ");
						   int restartgame=scanner.nextInt();
						   
						   //choose if restart game
						   if (restartgame==1)
							   System.exit(0);
						   else
						   {
							   restart=true;
							   System.out.println("Game restart");
							   break;
						   }
					   }
					   
					   else if (input_no=='c' && change_question_left>0)
					   {
						   restart=true;
						   gameover = true;
						   need_change_question=true;
						   change_question_left--;
						   System.out.println("number of times allow to change question: "+change_question_left--);
						   t.cancel(); //Cancel current timer
					   }
					   else if (input_no=='c' && change_question_left==0)
						   System.out.println("No question change allow!");
					   else if (input_no=='t'){
						   reset_question = true;
					   }
					   else if (input_no=='h')
					   {
						   if(m.hint_ava())
							   m.get_hint();	
						   else 
							   System.out.println("No more hints!");
					   }
					   else			
					   {
						   step=m.count_step(step);
						   if (m.validate_input(xPosition, yPosition,input,input_no,display)) 
						   {
							   m.set_board(xPosition, yPosition, input_no);
							   m.print_board();	        	   
							   System.out.println("Added X:"+xPosition+" Y:"+yPosition+" Number:"+input_no);
							   reset_question = false;
							   m.show_step(step);
							   
			        	   }	        	        	       
						   else 
						   {
						      System.out.println("Invalid Input.");	  
						      m.show_step(step);
						   }
					   	}
					   	if(m.gamewin())
					   	{
						   System.out.println("Game Win!");
						   System.out.print("[0]Restart the game or [1]Exit?: ");
						   int continuee;
						   continuee=scanner.nextInt();
						   if(continuee == 0)
						   {
							   gameover = true;
							   need_change_question=false;
							   restart = true;
							   t.cancel();
						   }
						   else
						   {
							   System.out.println("Game exit!");
							   System.exit(0);
						   }
					   	}
					   	if(m.gameover())
					   	{
						   System.out.println("Game Over!");
						   System.out.print("[0]Restart the game or [1]Exit?: ");
						   int continuee;
						   continuee=scanner.nextInt();
						   if(continuee == 0)
						   {
							   gameover = true;
							   need_change_question=false;
							   restart = true;
							   t.cancel();
						   }
						   else
						   {
							   System.out.println("Game exit!");
							   System.exit(0);
						   }
					   	}
				}
        	}
        }
 		scanner.close();
	}   
}